home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / perl / examples / burst < prev    next >
Encoding:
Text File  |  2000-03-28  |  9.0 KB  |  274 lines

  1. #!/usr/app/bin/perl
  2.  
  3. eval 'exec /usr/app/bin/perl  -S $0 ${1+"$@"}'
  4.     if 0; # not running under some shell
  5.  
  6. # <sjburges@gimp.org> 
  7. #
  8. use Gimp;
  9. use Gimp::Fu;
  10. use Gimp::Util;
  11.  
  12. # This script was requested by jimmac, and I thought it sounded moderately
  13. # useful.  I could have just made a couple selection masks and made it 
  14. # moderately useful, but instead I redid all the math myself to make it
  15. # intresting and have a really nice effect on the end points (rather than
  16. # chopping off odd-shaped brushes when the ellipse ends).
  17.  
  18. # Its good to exercise the ol geometry skills every now and then ;)
  19. # Enjoy,
  20. #  Seth Burgess <sjburges@gimp.org>
  21.  
  22. ####-----
  23. # Revision 03/18/2000
  24. #  Changed second angle to be a sweep measurement, not an absolute angle (I
  25. #  found that I was calculating a lot more by hand than I should be when
  26. #  using it)
  27. #  
  28. #  Also fixed up a bug that I'd covered up, and did a decent for loop for
  29. #  a change.  Fixed up rectangle to not mess up on corner areas.
  30. #  Lastly, I added a special case for 360 degrees - don't redraw the last
  31. #  line for a full circle; instead re-adjust end point.  I'm not entirely
  32. #  happy with this solution, but its close to what I expect to happen.  I
  33. #  don't desire to litter the interface with more strange options if possible
  34. #  and I suspect most users will never notice.
  35. #
  36.  
  37.  
  38.  
  39. # Gimp::set_trace(TRACE_ALL);
  40.  
  41. # find an equivalent polar value in the range of 0 to 2 pi 
  42. sub find_in_2pi
  43. {
  44.   my ($ang) = @_;
  45.   if ($ang < 0)
  46.     {
  47.        return ($ang - int($ang/(2*3.1415926))*2*3.1415926 + 2*3.1415926);
  48.     }
  49.   return ($ang - int($ang/(2*3.1415926))*2*3.1415926);
  50. }
  51.  
  52. # actual script
  53.  
  54. register "burst",
  55.   "Bursts from a central location\n",
  56.   "Creates a Burst of various sizes from the center of the currently 
  57. selected areas.  Can create either an elliptical burst, or some portion
  58. of said burst.  Also, you can specify how much (in pixels) to leave blank on
  59. the inside and the outside of the burst.  This uses whatever the current 
  60. brush settings are, and lets you control which direction to have it draw the
  61. fades from if you have Fade set\n",
  62.   "Seth Burgess",
  63.   "Seth Burgess <sjburges\@gimp.org>",
  64.   "1999-07-31",
  65.   N_"<Image>/Filters/Render/Burst...",
  66.   "*",
  67.   [
  68.    [PF_RADIO, "shape", "Shape To Burst Into", 0,  [Rectangle => 1, Ellipse=> 0]],
  69.    [PF_RADIO, "fade_dir", "Fade Direction (if fade is set)", 0,  [In => 1, Out => 0]],
  70.    [PF_VALUE, 'spokes', "How many spokes", 16],
  71.    [PF_VALUE, 'inside_pixels', "Inside Pixels", 10],
  72.    [PF_VALUE, 'outside_pixels', "Outside Pixels", 10], 
  73.    [PF_SLIDER, 'start_angle', "Angle to start at, with 0 being left, and sweeping counter-clockwise.", 0, [-360, 360, 1]],
  74.    [PF_SLIDER, 'arc_angle', "How many degrees to arc through.", 360, [-360, 360, 1]]
  75.   ],
  76.   [],
  77.   [],
  78.   sub {
  79.     my($img,$layer, $shape, $fade_dir, $points, 
  80.        $inside_pixels, $outside_pixels, $start_angle, $arc_angle) =@_;
  81.     
  82.     $pi = 3.1415927;
  83.     
  84.     # Special case 360
  85.     if (abs($arc_angle) == 360) 
  86.       {
  87.         $end_angle = $start_angle + $arc_angle - abs ($arc_angle/$points);
  88.       }
  89.     else 
  90.       {
  91.         $end_angle = $start_angle + $arc_angle;
  92.       }
  93.       
  94.     eval { $img->undo_push_group_start };
  95.  
  96.     Gimp->progress_init("Burst");    
  97.     $progress_increment = 1/$points;
  98.     $progress = 0;
  99.  
  100.     ($dumb, $x1, $y1, $x2, $y2) = $img->selection_bounds;
  101.     # $img->selection_none;
  102.     
  103.     $width = $x2 - $x1;
  104.     $height = $y2 - $y1;
  105.     
  106. #    print "X1 = $x1, X2 = $x2, Y1 = $y1, Y2 = $y2\n";
  107.     $center_x = $x1 + $width/2;
  108.     $center_y = $y1 + $height/2;
  109.  
  110.     if ($start_angle > $end_angle)
  111.       { # swap them
  112.         $angle = $end_angle;
  113.         $end_angle = $start_angle;
  114.         $start_angle = $angle;
  115.       }
  116.  
  117.     if ($shape == 0) 
  118.       { #ellipse
  119.         # do $points worth
  120.         for ($i = 0;
  121.              $i < $points;
  122.          #$angle <$end_angle*$pi/180-0.01; 
  123.              $i++ )
  124.           {
  125.             $angle = $i * abs($start_angle-$end_angle)*$pi/($points-1)/180;
  126.             $angle += $start_angle*$pi/180;
  127.         
  128.             # use the major/minor axis description of an ellipse:
  129.             # x^2   y^2
  130.             # --- + --- = 1
  131.             # a^2   b^2
  132.             # 
  133.             # where a is the x axis, b is the y axis, and the equation of
  134.             # a line passing through 0 (y=mb).  Solve for x&y, and pick the
  135.             # correct one for the angle.
  136.  
  137.             $a = $width/2 - $outside_pixels;
  138.             $b = $height/2 - $outside_pixels;
  139.  
  140.             # dimensions for an "inside ellipse"
  141.             $c = ($a>$b)?$inside_pixels:$inside_pixels*$a/$b;
  142.             $d = ($a>$b)?$inside_pixels*$b/$a:$inside_pixels;
  143.  
  144.             # get the slope
  145.             $m = sin($angle)/cos($angle);
  146.             if ($m ==0) { $m = 0.000000000001; } #avoid div by 0
  147.             if ($c ==0) { $c = 0.000000000001; } #avoid div by 0
  148.             if ($d ==0) { $d = 0.000000000001; } #avoid div by 0
  149.         
  150.             # find the positive solution of the quadratic for the endpoints 
  151.             $x = sqrt(1/((1/$a/$a)+($m*$m/$b/$b)));
  152.             $y = sqrt(1/((1/($m*$m*$a*$a))+(1/$b/$b)));
  153.  
  154.             # and find the starting points in the same manner
  155.             $x_start = sqrt(1/((1/$c/$c)+($m*$m/$d/$d)));
  156.             $y_start = sqrt(1/((1/($m*$m*$c*$c))+(1/$d/$d)));
  157.  
  158.             # pick the right solution of the quadratic
  159.             if ((find_in_2pi($angle) < $pi/2) || 
  160.              (find_in_2pi($angle) > 3*$pi/2)) 
  161.               { 
  162.                 $x = -$x; 
  163.                 $x_start = -$x_start;
  164.               }
  165.             if (find_in_2pi($angle) > $pi) 
  166.               {
  167.                 $y = -$y; 
  168.                 $y_start = -$y_start;
  169.               }
  170.             # do translations to center stuff
  171.             $x = $x + $center_x;
  172.             $y = $y + $center_y;
  173.             $x_start = $x_start + $center_x;
  174.             $y_start = $y_start + $center_y;
  175.  
  176.             if ($fade_dir == 1) 
  177.               {        
  178.                 $layer->paintbrush_default(4, [$x, $y, $x_start, $y_start]);
  179.               }
  180.             else
  181.               {
  182.                 $layer->paintbrush_default(4, [$x_start, $y_start, $x, $y]);
  183.               }
  184.             $progress += $progress_increment;
  185.             Gimp->progress_update($progress);
  186.          }
  187.       }
  188.     else 
  189.       { #rectangle
  190.         # The idea here is to see where the line intersects with the
  191.         # rightmost line.  If the abs of that is higer than the height, 
  192.         # see where it intersects the top instead.
  193.  
  194.         #print "width = $width, height = $height\n";        
  195.  
  196.         for ($i = 0;
  197.              $i < $points;
  198.              $i++ )
  199.           {
  200.             $angle = $i * abs($start_angle-$end_angle)*$pi/($points-1)/180;
  201.             $angle += $start_angle*$pi/180;
  202.         
  203.             # get the slope
  204.             $m = sin($angle)/cos($angle);
  205.             if (abs($m*$width/2) < $height/2)
  206.               { # draw on the right/left borders        
  207.                 $x = $width/2-$outside_pixels;
  208.                 $y = $m*($width/2-$outside_pixels);
  209.                 $x_start = ($width>$height)
  210.                         ?($inside_pixels)
  211.                         :($inside_pixels*$width/$height);
  212.                 $y_start = ($width>$height)
  213.                         ?($m*$inside_pixels)
  214.                         :($m*$inside_pixels*$width/$height);
  215.               }
  216.            else
  217.              { # draw on the top/bottom borders
  218.                 $y = $height/2-$outside_pixels;
  219.                 $x = ($height/2-$outside_pixels)/$m;        
  220.                 $y_start = ($width>$height)
  221.                         ?($inside_pixels*$height/$width)
  222.                         :($inside_pixels);
  223.                 $x_start = ($width>$height)
  224.                         ?($inside_pixels*$height/$width/$m)
  225.                         :($inside_pixels/$m);
  226.              } 
  227.           # the method of finding points by lines like above makes picking right
  228.           # values kinda icky, as shown by these if statements. 
  229.           if ((find_in_2pi($angle) <= $pi/2) || 
  230.           (find_in_2pi($angle) > 3*$pi/2)) 
  231.             { 
  232.                 $x = -abs($x); 
  233.                 $x_start = -abs($x_start);
  234.             }
  235.           else
  236.             {
  237.                 $x = abs($x);
  238.                 $x_start = abs($x_start);
  239.             }
  240.  
  241.           if (find_in_2pi($angle) > $pi) 
  242.             {
  243.               $y = -abs($y); 
  244.               $y_start = -abs($y_start);
  245.             }
  246.           else 
  247.             {
  248.               $y = abs($y); 
  249.               $y_start = abs($y_start);
  250.             }
  251.           # do translations to center stuff
  252.           $x = $x + $center_x;
  253.           $y = $y + $center_y;
  254.           $x_start = $x_start + $center_x;
  255.           $y_start = $y_start + $center_y;
  256.           if ($fade_dir == 1) 
  257.             {        
  258.               $layer->paintbrush_default(4, [$x, $y, $x_start, $y_start]);
  259.             }
  260.           else
  261.             {
  262.               $layer->paintbrush_default(4, [$x_start, $y_start, $x, $y]);
  263.             }
  264.           $progress += $progress_increment;
  265.           Gimp->progress_update($progress);
  266.         }
  267.     } 
  268.   eval { $img->undo_push_group_end };
  269.   return();
  270. };
  271.  
  272. exit main;
  273.